home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Disc to the Future 2
/
Disc to the Future Part II Programmer's Reference (Wayzata Technology)(6013)(1992).bin
/
MAC
/
THINKC
/
4_0
/
MORSE_CD
/
MORSE_CD.C
next >
Wrap
Text File
|
1989-11-11
|
10KB
|
419 lines
/*
Example of a cdev/INIT program written in THINK C 3.02.
The 'INIT' will play some morse code at startup, using parameters in
the 'PARM' resource. The 'cdev' allows to modify these parameters
through the control panel DA.
There are two other projects that build code resources, and these code
resources must be included in 'Morse CDEV ╣.rsrc' with ResEdit:
Morse Play ╣ --> 'PLAY' resource, contains the function MorsePlay()
Morse INIT ╣ --> 'INIT' resource, called at system startup
Use 'Set Project Type...', then select 'Code Resource', set type 'cdev',
ID -4064, purgeable. The file type should be set to type 'cdev' with
creator 'LXYZ'.
*/
#define CREATOR 'LXYZ'
#define ICON -4064 /* Resource id of 'ICN#' */
#define PARM -4048 /* Resource id of 'PARM' */
#define PLAY -4048 /* Resource id of 'PLAY' */
#define CURS -4064 /* Resource id of 'CURS' */
/* 'DITL' items */
#define iEnable 1 /* Enable INIT (radio button) */
#define iDisable 2 /* Disable INIT (radio button) */
#define iText 3 /* Text to morse (editText) */
#define iIcon 4 /* iconItem */
#define iFrequency 5 /* Frequency (editText) */
#define iVolume 6 /* Volume (editText) */
#define iSpeed 7 /* Speed (editText) */
#define iVersion 11 /* Version (staticText) */
#define MorsePlay(a,b,c,d) (*mp)(a,b,c,d)
typedef void (*PF)(); /* Pointer to function returning void */
typedef struct Parameter { /* Structure of 'PARM' resource */
Boolean enable; /* Enable INIT */
short parm[3]; /* Frequency, volume and speed */
char text[256]; /* Pascal string, text to morse */
} Parameter;
typedef struct Storage { /* Storage needed between calls to 'cdev' */
DialogPtr dlgPtr; /* Pointer to the control pannel dialog */
short dlgItems; /* Dialog items used by control pannel */
Cursor curs; /* Our cursor */
Boolean dirty; /* Set if var modified */
Boolean toggle;
Parameter var;
} Storage, *StoragePtr, **StorageHdl;
char ERNY[] = "\p DE LX1YZ \0";
#define FREQ 800
#define VOLUME 64
#define SPEED 3
/* ----- Function prototypes ------------------------------------------- */
void Invalidate (StoragePtr, short);
Handle GetCtlHdl (StoragePtr, short);
Boolean NewValues (StoragePtr);
void Hit (StoragePtr, short);
void Key (EventRecord *, DialogPtr, short);
long Init (DialogPtr, short);
void Hide (DialogPtr, short);
void Bye (StoragePtr);
pascal long main (short,short,short,short,EventRecord *,long,DialogPtr);
/* ----- Get handle for given dialog item ------------------------------ */
Handle GetCtlHdl (p, item)
register StoragePtr p;
register short item;
{
Handle Hdl;
Rect r;
short type;
GetDItem(p->dlgPtr, item + p->dlgItems, &type, &Hdl, &r);
return Hdl;
}
/* ----- Erase and invalidate dialog item ------------------------------ */
void Invalidate (p, item)
register StoragePtr p;
register short item;
{
short type;
Handle hdl;
Rect r;
GetDItem(p->dlgPtr, item + p->dlgItems, &type, &hdl, &r);
EraseRect(&r);
InvalRect(&r);
}
/* ----- Read new values from TextEdit fields -------------------------- */
Boolean NewValues (p)
register StoragePtr p;
{
register char s[256];
register Handle ctrl;
register short i;
register Boolean err;
long v;
ctrl = GetCtlHdl(p, iText);
GetIText(ctrl, s);
if (!EqualString(s, p->var.text, TRUE, TRUE)) {
p->dirty = TRUE;
BlockMove(s, p->var.text, *s + 1);
}
for (i = iFrequency; i <= iSpeed; i++) {
ctrl = GetCtlHdl(p, i);
GetIText(ctrl, s);
StringToNum(s , &v);
switch (i) {
case iFrequency:
err = v < 200 || v > 2000;
break;
case iVolume:
err = v > 255;
break;
case iSpeed:
err = v < 1 || v > 10;
break;
}
if (err) {
SysBeep(1);
SelIText(p->dlgPtr, p->dlgItems + i, 0, 32767);
return TRUE; /* Error */
}
if (p->var.parm[i - iFrequency] != v) {
p->dirty = TRUE;
p->var.parm[i - iFrequency] = v;
}
}
return FALSE; /* No error */
}
/* ----- Handle a hit in one of our DITL items ------------------------- */
void Hit (p, item)
register StoragePtr p;
register short item;
{
register PF mp, *mh;
Handle ctrl, text;
switch (item) {
case iEnable:
p->dirty = TRUE;
p->var.enable = TRUE;
SetCtlValue(GetCtlHdl(p, iEnable), TRUE);
SetCtlValue(GetCtlHdl(p, iDisable), FALSE);
break;
case iDisable:
p->dirty = TRUE;
p->var.enable = FALSE;
SetCtlValue(GetCtlHdl(p, iEnable), FALSE);
SetCtlValue(GetCtlHdl(p, iDisable), TRUE);
break;
case iIcon:
if (NewValues(p))
break;
Invalidate(p, item);
if (mh = (PF *)GetResource('PLAY', PLAY)) {
HLock(mh);
mp = *mh;
PtoCstr(p->var.text);
MorsePlay(p->var.text, p->var.parm[0],
p->var.parm[1], p->var.parm[2]);
CtoPstr(p->var.text);
ReleaseResource(mh);
}
break;
case iVersion:
Invalidate(p, item);
if (mh = (PF *)GetResource('PLAY', PLAY)) {
HLock(mh);
mp = *mh;
MorsePlay(ERNY + 1, FREQ, VOLUME, SPEED);
ReleaseResource(mh);
}
ctrl = GetCtlHdl(p, iVersion);
p->toggle = !p->toggle;
if (p->toggle)
SetIText(ctrl, ERNY);
else
if (text = GetResource(CREATOR, 0)) {
HLock(text);
SetIText(ctrl, *text);
ReleaseResource(text);
}
break;
}
}
/* ----- Handle keystrokes --------------------------------------------- */
void Key (event, dialog, num)
register EventRecord *event;
register DialogPtr dialog;
register short num;
{
register char key;
key = event->message & charCodeMask;
if (event->modifiers & cmdKey) {
event->what = nullEvent;
switch (key) {
case 'k': /* Cut */
case 'K':
DlgCut(dialog);
break;
case 'c': /* Copy */
case 'C':
DlgCopy(dialog);
break;
case 'v': /* Paste */
case 'V':
DlgPaste(dialog);
break;
default:
SysBeep(1);
}
} else
if (key != '\t' && key != '\b')
switch (((DialogPeek)dialog)->editField + 1 - num) {
case iText:
if (key >= 'a' && key <= 'z')
key -= 'a' - 'A';
if (key < ' ' || key > '_') {
SysBeep(1);
event->what = nullEvent;
}
break;
case iFrequency:
case iVolume:
case iSpeed:
if (key < '0' || key > '9') {
SysBeep(1);
event->what = nullEvent;
}
break;
}
}
/* ----- Hide EditText items ------------------------------------------- */
/* See TN #251 why the EditText items should be hidden */
void Hide (dialog, num)
register DialogPtr dialog;
register short num;
{
HideDItem(dialog, num + iText);
HideDItem(dialog, num + iFrequency);
HideDItem(dialog, num + iVolume);
HideDItem(dialog, num + iSpeed);
}
/* ----- Initialize the cdev ------------------------------------------- */
long Init (dialog, num)
DialogPtr dialog;
short num;
{
StorageHdl h;
register StoragePtr p;
register Handle text;
register Handle ctrl;
register short i;
char s[256];
CursHandle ch;
if (h = (StorageHdl)NewHandle(sizeof(Storage))) {
HLock(h);
p = *h;
p->dlgPtr = dialog;
p->dlgItems = num;
if (ch = GetCursor(CURS))
p->curs = **ch;
p->dirty = FALSE;
p->toggle = FALSE;
if ((text = GetResource('PARM', PARM)) && !ResError()) {
BlockMove(*text, &p->var, sizeof(Parameter));
ReleaseResource(text);
} else {
p->var.enable = FALSE;
p->var.parm[0] = FREQ;
p->var.parm[1] = VOLUME;
p->var.parm[2] = SPEED;
BlockMove(ERNY, p->var.text, *ERNY + 1);
}
SetCtlValue(GetCtlHdl(p, iEnable), p->var.enable);
SetCtlValue(GetCtlHdl(p, iDisable), !p->var.enable);
for (i = iFrequency; i <= iSpeed; i++) {
NumToString(p->var.parm[i - iFrequency], s);
ctrl = GetCtlHdl(p, i);
SetIText(ctrl, s);
}
ctrl = GetCtlHdl(p, iText);
SetIText(ctrl, p->var.text);
SelIText(dialog, num + iText, 0, 32767);
if (text = GetResource(CREATOR, 0)) {
HLock(text);
ctrl = GetCtlHdl(p, iVersion);
SetIText(ctrl, *text);
ReleaseResource(text);
}
HUnlock(h);
} else
Hide(dialog, num);
return (long)h;
}
/* ----- Bye bye ------------------------------------------------------- */
void Bye (p)
register StoragePtr p;
{
register Handle text;
register char empty[1];
if (p->dirty) {
empty[0] = 0;
if (text = GetResource('PARM', PARM)) {
RmveResource(text);
DisposHandle(text);
}
if (text = NewHandle((long)sizeof(Parameter))) {
BlockMove(&p->var, *text, sizeof(Parameter));
AddResource(text, 'PARM', PARM, empty);
if (!ResError()) {
WriteResource(text);
ReleaseResource(text);
}
}
}
}
/* ----- The 'cdev' dispatch function ---------------------------------- */
pascal long main (message, item, num, id, event, value, dialog)
short message;
register short item;
register short num;
short id;
EventRecord *event;
register long value;
DialogPtr dialog;
{
asm {
MOVE A4,-(SP) /* Save A4 */
MOVE.L A0,A4 /* A4 used for global and static data */
}
if (message != initDev && message != macDev &&
(!value || value == cdevUnset))
value = 0;
else
switch (message) {
case initDev: /* Initialization */
TEFromScrap();
value = Init(dialog, num);
break;
case hitDev: /* User clicked dialog item */
HLock(value);
Hit(*(StorageHdl)value, item - num);
HUnlock(value);
break;
case closeDev: /* Selected another cdev or CP closed */
ZeroScrap();
TEToScrap();
if (value) {
HLock(value);
Bye(*(StorageHdl)value);
DisposHandle(value);
value = 0;
}
break;
case activDev: /* Activate event */
TEFromScrap();
break;
case deactivDev: /* Deactivate event */
ZeroScrap();
TEToScrap();
break;
case keyEvtDev: /* Key-down or auto-key event */
Key(event, dialog, num);
break;
case cutDev:
DlgCut(dialog);
break;
case copyDev:
DlgCopy(dialog);
break;
case pasteDev:
DlgPaste(dialog);
break;
case clearDev:
DlgDelete(dialog);
break;
case 14 /* cursorDev (see TN #215) */:
if (value)
SetCursor(&(**(StorageHdl)value).curs);
break;
}
asm {
MOVE (SP)+,A4 /* Restore A4 */
}
return value;
}